import re
"""re模块常用方法"""

#1.  re.findall(pattern, string)
    #作用：查找所有匹配的字串
    #返回值：字符串列表(无分组)或元组(有分组)
numbers = re.findall(r'\d+', 'a1b22c333d')
print(numbers) #['1', '22', '333']

#2. re.finditer(pattern, string)
    #根据打印结果，以及for loop我们大概可以猜出，该方法返回的是一个迭代器,而且应该是是一个match对象的迭代器
    # 作用：查找所有匹配的子串，返回迭代器
    # 返回值：Match对象的迭代器
matchs_iter = re.finditer(r'\d+', 'a1b22c333d')
for match in matchs_iter:
    print(match.group(), match.span()) #根据输出结果，group返回的是匹配字符串，span返回的是每个每组(begin,end)的位置
print(type(matchs_iter)) #<class 'callable_iterator'>

# 1 (1, 2)
# 22 (3, 5)
# 333 (6, 9)

#3. re.search(pattern, string)
#根据打印结果可以推断出该方法匹配第一个满足条件的匹配结果，返回的对象是一个match对象
    # 作用：扫描整个字符串查找第一个匹配
    # 返回值：Match对象或None
result = re.search(r'\d+', 'a1b22c333d')
print(result.group()) #1
print(type(result)) #<class 're.Match'>

#4. re.match(pattern, string)
    #根据打印结果，该方法只会从字符串开头进行匹配，满足条件返回match对象，否则返回None，注意search是从匹配对象整体检查
    # 作用：从字符串开头匹配模式
    # 返回值：匹配对象(Match对象)或None
res = re.match(r'hello', 'hello world')
print(type(res)) #<class 're.Match'>
if res:
    print('匹配成功：', res.group()) #匹配成功： hello
else:
    print('匹配失败')

res2 = re.match(r'\d+', 'a1b22c333d')
print(type(res2)) #<class 'NoneType'>
if res2:
    print('匹配成功：', res.group())
else:
    print('匹配失败') #匹配失败

"""
find和search的语义差别：
    ·匹配数量：findall 会找出字符串里所有匹配的子串；search 只找第一个匹配的子串。
    ·返回值类型：findall 返回列表，列表元素可以是字符串或元组；search 返回 Match 对象或 None。
    ·使用场景：若要获取字符串中所有匹配的内容，就用 findall；若只关心第一个匹配项，使用 search 效率更高。
"""

#预加载正则表达式
obj = re.compile(r'\d+')
numbers = re.findall(obj, 'a1b22c333d')
print(numbers)

#在正则表达式前的字符‘r'有何含义：
    # 在正则表达式里，r 前缀用于创建原始字符串。原始字符串会把反斜杠 \ 当作普通字符，而非转义字符。
    # 在正则表达式中，反斜杠 \ 常被用来表示特殊字符，例如 \d 表示匹配数字，\w 表示匹配单词字符。
    # 若不用 r 前缀，就需要对反斜杠进行转义，代码会更复杂。


# 三、Match对象常用方法
# 正则匹配成功后返回的Match对象有以下常用方法：

# 方法/属性	说明
# group()	返回匹配的字符串
# group(n)	返回第n个分组内容
# groups()	返回所有分组的元组
# start()	返回匹配的开始位置
# end()	返回匹配的结束位置
# span()	返回(开始,结束)位置的元组
